package gwtappcontainer.server.apis.admin;

import gwtappcontainer.server.apis.admin.Roles.Role;
import gwtappcontainer.server.apps.APIBase;
import gwtappcontainer.server.apps.APIException;
import gwtappcontainer.shared.apis.APIResponse;
import gwtappcontainer.shared.apis.APIResponse.Status;
import gwtappcontainer.shared.apis.admin.RoleProp;
import gwtappcontainer.shared.apis.admin.UserProp;

import java.util.List;

import javax.inject.Named;

import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.config.ApiMethod.HttpMethod;
import com.google.appengine.api.users.User;

@Api (name = "admin", 
	scopes = { "https://www.googleapis.com/auth/userinfo.email" }
)
public class AdminAPI extends APIBase {	
			
	@ApiMethod(httpMethod = HttpMethod.GET, path = "listroles")
	public APIResponse getAllRoles() {
		
		try {
			RoleRepository repository = new RoleRepository();
			List<RoleProp> allProps = repository.getAllRoles();
			
			APIResponse resp = new APIResponse();
			
			resp.object = allProps;
			resp.statusCode = Status.SUCCESS;
			
			if (0 == allProps.size())
				resp.userFriendlyMessage = "No roles available";
						
			return resp;
			
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
		
	@ApiMethod(path = "addrole", httpMethod = HttpMethod.GET)
	public APIResponse addRole(@Named("role") String role, User user) {
		
		try {
			//only allowed for developers
			ensureRole(user, Role.DEVELOPER);
																	
			RoleRepository repository = new RoleRepository();
			
			RoleProp prop = repository.addRole(role);
			
			APIResponse resp = new APIResponse();
			resp.statusCode = Status.SUCCESS;
			resp.object = prop;			
			return resp;
		
		} catch(Exception ex)  {
			return new APIResponse(ex);
		}
	}
	
	
	@ApiMethod(path = "renamerole", httpMethod = HttpMethod.PUT)
	public APIResponse renameRole(@Named("existing_name") String existingName, 
			@Named("new_name") String newName, User user) {
		
		try {
		
			//only allowed for developers
			ensureRole(user, Role.DEVELOPER);			
											
			RoleRepository repository = new RoleRepository();
			RoleProp prop = repository.updateRole(existingName, newName);
			
			APIResponse resp = new APIResponse();
			resp.statusCode = Status.SUCCESS;
			resp.object = prop;
			return resp;
		
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}	
	
	@ApiMethod(path = "deleterole", httpMethod = HttpMethod.DELETE)
	public APIResponse deleteRole(@Named("role") String role, User user) {
		
		try {
			ensureRole(user, Role.DEVELOPER);
											
			RoleRepository repository = new RoleRepository();
			repository.deleteRole(role);
			
			APIResponse resp = new APIResponse();
			resp.statusCode = Status.SUCCESS;
			
			return resp;
		
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
	
	@ApiMethod(path = "getloggedinemail", httpMethod = HttpMethod.GET)
	public APIResponse getLoggedInEmail(User user) {		
		try {
			APIResponse resp = new APIResponse();
			
			resp.object = "not logged in";		
			if (null != user)
				resp.object = user.getEmail();
			
			return resp;
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
	
	@ApiMethod(path = "getrolesforuser", httpMethod = HttpMethod.GET)
	public APIResponse getRolesForUser(@Named("email") String email) {		
		try {													
			
			UserRepository repository = new UserRepository();
			email = email.toLowerCase();
			UserProp prop = repository.getUserByEmail(email);
			
			APIResponse resp = new APIResponse();
			
			if (null == prop) {
				resp.statusCode = Status.ERROR_INVALID_USER;
				resp.object = "[" + email + "] is not set up as a user";
				return resp;
			}
						
			resp.statusCode = Status.SUCCESS;
			resp.object = prop;
			
			return resp;
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
	
	@ApiMethod(path = "getrolesforloggedinuser", httpMethod = HttpMethod.GET)
	public APIResponse getRolesForLoggedInUser(User user) {		
		try {										
			if (user == null) {
				throw new APIException(Status.ERROR_LOGIN_REQUIRED, "Login required");
			}
			
			String email = user.getEmail();
			APIResponse resp = getRolesForUser(email);
							
			return resp;
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
	
	@ApiMethod(httpMethod = HttpMethod.GET, path = "listusers")
	public APIResponse getAllUsers() {
		try {
			UserRepository userRepository = new UserRepository();
			List<UserProp> allProps = userRepository.getAllUsers();
			
			if (0 == allProps.size()) {
				throw new APIException(Status.ERROR_RESOURCE_DOES_NOT_EXIST, "No users available");				
			}
			
			APIResponse resp = new APIResponse();
			resp.statusCode = Status.SUCCESS;
			resp.object = allProps;
			
			return resp;
			
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
	
	@ApiMethod(path = "adduser", httpMethod = HttpMethod.PUT)
	public APIResponse addUser(@Named("email") String email, User user) {				
		
		try {
			//only PORTAL_ADMIN can add user
			ensureRole(user, Role.PORTAL_ADMIN);			
											
			UserRepository repository = new UserRepository();
			UserProp prop = repository.addUser(email);
			
			APIResponse resp = new APIResponse();
			resp.statusCode = Status.SUCCESS;
			resp.object = prop;
			return resp;
			
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
	
	@ApiMethod(path = "assignrole", httpMethod = HttpMethod.PUT)
	public APIResponse assignRoleToUser(@Named("email") String email, 
			@Named("role") String role, User user) {	
		try {		
			ensureRole(user, Role.PORTAL_ADMIN); 	 				
						
			UserRepository repository = new UserRepository();
			UserProp prop = repository.changeUserPermission(email, role, true);
			
			return new APIResponse(Status.SUCCESS, prop);
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}		
	
	@ApiMethod(path = "unassignrole", httpMethod = HttpMethod.PUT)
	public APIResponse unassignRoleToUser(@Named("email") String email, 
			@Named("role") String role, User user) {	
		
		try {	
			ensureRole(user, Role.PORTAL_ADMIN);
			//GateKeeper.throwExceptionIfNeitherPortalAdminNorDeveloper(user);
						
			UserRepository repository = new UserRepository();
			UserProp prop = repository.changeUserPermission(email, role, false);
			
			return new APIResponse(Status.SUCCESS, prop);
			
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}				
}
